package br.edu.ufcg.dsc.psoo.mymoney.controller.implementation;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import br.edu.ufcg.dsc.psoo.mymoney.controller.GroupController;
import br.edu.ufcg.dsc.psoo.mymoney.controller.Validator;
import br.edu.ufcg.dsc.psoo.mymoney.controller.exceptions.AccountNotFoundException;
import br.edu.ufcg.dsc.psoo.mymoney.controller.exceptions.GroupNotFoundException;
import br.edu.ufcg.dsc.psoo.mymoney.controller.exceptions.InvalidGroupException;
import br.edu.ufcg.dsc.psoo.mymoney.model.bean.Account;
import br.edu.ufcg.dsc.psoo.mymoney.model.bean.Group;
import br.edu.ufcg.dsc.psoo.mymoney.model.bean.User;
import br.edu.ufcg.dsc.psoo.mymoney.model.dao.AccountDAO;
import br.edu.ufcg.dsc.psoo.mymoney.model.dao.GroupDAO;
import br.edu.ufcg.dsc.psoo.mymoney.model.hibernate.HibernateUtil;

/**
 * Controller respons�vel pela valida��o e opera��es envolvendo grupos
 * 
 * @author leonardo
 * 
 */
public class GroupControllerImpl implements GroupController {
	private GroupDAO groupDAO;
	private AccountDAO accountDAO;
	private SessionFactory sf = HibernateUtil.getSessionFactory();
	private Session session;

	private Validator validator = new Validator();

	/**
	 * Construtor padrao recebendo o DAO de Group via Injection (Mentawai)
	 * 
	 * @param groupDAO
	 */
	public GroupControllerImpl(GroupDAO groupDAO, AccountDAO accountDAO) {
		this.groupDAO = groupDAO;
		this.accountDAO = accountDAO;
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#closeSession()
	 */
	public void closeSession() {
		session.close();
		groupDAO.setSession(session);
		accountDAO.setSession(session);
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#create(br.edu.ufcg.dsc.psoo.mymoney.model.bean.Group)
	 */
	public Group create(Group group) throws InvalidGroupException,
			AccountNotFoundException {
		openSession();
		Account acc = new Account();
		acc = accountDAO.findByName(group.getAccount().getName());
		if (group.getAccount() == null) {
			throw new AccountNotFoundException("Conta nao encontrada!");
		} else {
			// campos em branco
			if (group.getName().equals("") || acc == null) {
				// campos obrigatórios
				throw new InvalidGroupException("Preencha todos os campos!");
			} else {
				List<Group> bdGroups = groupDAO.findByName(group.getName());
				if (bdGroups.size()!=0) {
					for (Group bdGroup : bdGroups) {
						if (bdGroup.getAccount().getName().equals(group.getAccount().getName()))
							throw new InvalidGroupException(
							"Nome ja registrado!");
						}
					
				} else {
					if (!validator.alfanumericValidator(group.getName(), 3, 20)) {
						throw new InvalidGroupException("Nome invalido!");
					}
				}
			}
		}
		// persiste no banco o novo usuário
		group.setAccount(acc);
		Group createdGroup = groupDAO.create(group);
		closeSession();
		return createdGroup;

	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#delete(java.lang.Long, java.lang.Long)
	 */
	public void delete(Long accountId, Long id) throws InvalidGroupException,
			GroupNotFoundException {
		openSession();
		Group g = new Group();
		g.setId(id);

		if (id == null)
			throw new GroupNotFoundException("Grupo nao encontrado!");
		else {
			Group group = groupDAO.load(g.getId());
			if (!(group.getAccount().getId().equals(accountId))) {
				throw new InvalidGroupException(
						"You don't have permission to delete this group!");
			} else {
				groupDAO.delete(group);
			}
		}
		closeSession();
	}
	
	public void deleteFromUser(Long userId, Long id)
			throws InvalidGroupException, GroupNotFoundException {
		openSession();
		if (id == null)
			throw new GroupNotFoundException("Group not found!");
		else {
			Group group = groupDAO.load(id);
			if (!(group.getAccount().getUser().getId().equals(userId))) {
				throw new InvalidGroupException(
						"You don't have permission to delete this group!");
			} else {
				groupDAO.delete(group);
			}
		}
		closeSession();
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#openSession()
	 */
	public void openSession() {
		session = sf.openSession();
		groupDAO.setSession(session);
		accountDAO.setSession(session);
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#setSessionFactory(org.hibernate.SessionFactory)
	 */
	public void setSessionFactory(SessionFactory sf) {
		this.sf = sf;
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#update(br.edu.ufcg.dsc.psoo.mymoney.model.bean.Group)
	 */
	public Group update(Group group) throws InvalidGroupException {
		
		Account ac = new Account();
		ac.setId(group.getAccount().getId());
		openSession();
		// campos em branco
		if (group.getName().equals("") || group.getAccount() == null
				|| accountDAO.load(ac.getId()) == null) {
			// campos obrigatórios
			throw new InvalidGroupException("Preencha todos os campos!");
		} else {
			openSession();
			Group g = groupDAO.load(group.getId());
			closeSession();
			if (g == null) {
				throw new InvalidGroupException("Grupo invalido para atualizacao!");
			} else {
				openSession();
				List<Group> bdGroups = groupDAO.findByName(group.getName());
				closeSession();
				if (bdGroups != null) {
					for (Group listGroup : bdGroups) {
						if (listGroup.getName().equals(group.getName())&&!listGroup.getId().equals(group.getId()))
						throw new InvalidGroupException("Nome ja registrado!");		
					}
				
				}
			else {
				if (!validator.alfanumericValidator(group.getName(), 3, 30)) {
					throw new InvalidGroupException("Nome invalido!");
				}
			}
			}
		}

		// persiste no banco o novo usuário
		openSession();
		Group updatedGroup = groupDAO.update(group);
		closeSession();
		return updatedGroup;

	}
	
	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.GroupContr#listAll(java.lang.Long)
	 */
	public List<Group> listAll(Long accountId) {
		openSession();
		Group findGroup = new Group();
		Account acc = new Account();
		acc.setId(accountId);
		findGroup.setAccount(acc);
		List<Group> groups = groupDAO.find(findGroup);
		closeSession();
		return groups;
	}
	
	public List<Group> listAllFromUser(Long userId) {
		openSession();
		Group findGroup = new Group();
		User u = new User();
		u.setId(userId);
		Account acc = new Account();
//		acc.setId(accountId);
		acc.setUser(u);
		findGroup.setAccount(acc);
		List<Group> groups = groupDAO.find(findGroup);
		closeSession();
		return groups;
	}
	
	@Override
	public List<Group> findByName(String name) {
		openSession();
		List<Group> groups = groupDAO.findByName(name);
		closeSession();
		return groups;
		
	}
	public Group loadById(Long id) {
		openSession();
		Group group = groupDAO.load(id);
		closeSession();
		return group;
		
	}
}